// Copyright (c) Appeon
// The following has been modified by Appeon under compliance with the Apache 2.0 license from the original work

// Copyright(c) 2002-2019, Npgsql
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written agreement
// is hereby granted, provided that the above copyright notice and this
// paragraph and the following two paragraphs appear in all copies.
//
// IN NO EVENT SHALL NPGSQL BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// Npgsql HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// NPGSQL SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE.THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND Npgsql
// HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
// OR MODIFICATIONS.

using System;
using System.Data.Common;
using JetBrains.Annotations;
using Npgsql;
using NpgsqlTypes;

namespace SnapObjects.Data.PostgreSql
{
    public class PostgreSqlTimeTypeMapping : PostgreSqlTypeMapping
    {
        public PostgreSqlTimeTypeMapping([NotNull] string storeType)
            : base(storeType, typeof(TimeSpan), NpgsqlDbType.Time)
        {
        }

        protected override void ConfigureParameter(DbParameter parameter, IAdoDbParameter adoDbParameter)
        {
            base.ConfigureParameter(parameter, adoDbParameter);

            if (parameter is NpgsqlParameter p)
            {
                p.NpgsqlDbType = NpgsqlDbType.Time;
            }
        }

        protected override string GenerateNonNullSqlLiteral(object value)
        {
            var ts = (TimeSpan)value;
            return ts.Ticks % 10000000 == 0
                ? FormattableString.Invariant($@"TIME '{(TimeSpan)value:hh\:mm\:ss}'")
                : FormattableString.Invariant($@"TIME '{(TimeSpan)value:hh\:mm\:ss\.FFFFFF}'");
        }

        public override TypeMapping Clone([NotNull] string dbTypeName, int? size)
        {
            return new PostgreSqlTimeTypeMapping(dbTypeName);
        }
    }

    public class PostgreSqlTimeTzTypeMapping : PostgreSqlTypeMapping
    {
        public PostgreSqlTimeTzTypeMapping([NotNull] string storeType)
            : base(storeType, typeof(DateTimeOffset), NpgsqlDbType.TimeTz)
        {
        }

        protected override void ConfigureParameter(DbParameter parameter, IAdoDbParameter adoDbParameter)
        {
            base.ConfigureParameter(parameter, adoDbParameter);

            if (parameter is NpgsqlParameter p)
            {
                p.NpgsqlDbType = NpgsqlDbType.TimeTz;
            }
        }

        protected override string GenerateNonNullSqlLiteral(object value)
            => FormattableString.Invariant($"TIMETZ '{(DateTimeOffset)value:HH:mm:ss.FFFFFFz}'");

        public override TypeMapping Clone([NotNull] string dbTypeName, int? size)
        {
            return new PostgreSqlTimeTzTypeMapping(dbTypeName);
        }
    }
}
